
/*
Copyright 2009 David Revell

This file is part of SwiFTP.

SwiFTP is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

SwiFTP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with SwiFTP.  If not, see <http://www.gnu.org/licenses/>.
*/

package lfr.ustc.ftp;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class CmdLIST extends CmdManager implements Runnable {
	public final static long MS_IN_SIX_MONTHS = 6 * 30 * 24 * 60 * 60 * 1000;
	private String input;

	public CmdLIST(SocketManager sessionThread, String input) {
		super(sessionThread);
		this.input = input;
	}

	public String listDirectory(StringBuilder response, File dir) {
		if (!dir.isDirectory()) {
			return "500 Internal error, listDirectory on non-directory\r\n";
		}

		File[] entries = dir.listFiles();
		if (entries == null) {
			return "500 Couldn't list directory. Check config and mount status.\r\n";
		}

		for (File entry : entries) {
			String curLine = makeLsString(entry);
			if (curLine != null) {
				response.append(curLine);
			}
		}
		return null;
	}

	protected String sendListing(String listing) {
		if (sessionThread.startUsingDataSocket()) {
		} else {
			sessionThread.closeDataSocket();
			return "425 Error opening data socket\r\n";
		}
		String mode = sessionThread.transmitType;
		sessionThread.sendInfo("150 Opening " + mode
				+ " mode data connection for file list\r\n");
		if (!sessionThread.sendData(listing)) {
			return "426 Data socket or network error\r\n";
		}
		sessionThread.closeDataSocket();
		sessionThread.sendInfo("226 Data transmission OK\r\n");
		return null;
	}

	public void run() {
		String errString = null;

		mainblock: {
			String param = getParameter(input);
			while (param.startsWith("-")) {
				param = getParameter(param);
			}
			File fileToList = null;
			if (param.equals("")) {
				fileToList = sessionThread.getWorkingDir();
			} else {
				if (param.contains("*")) {
					errString = "550 LIST does not support wildcards\r\n";
					break mainblock;
				}
				fileToList = new File(sessionThread.getWorkingDir(), param);
				if (violatesChroot(fileToList)) {
					errString = "450 Listing target violates chroot\r\n";
					break mainblock;
				}
			}
			String listing;
			if (fileToList.isDirectory()) {
				StringBuilder response = new StringBuilder();
				errString = listDirectory(response, fileToList);
				if (errString != null) {
					break mainblock;
				}
				listing = response.toString();
			} else {
				listing = makeLsString(fileToList);
				if (listing == null) {
					errString = "450 Couldn't list that file\r\n";
					break mainblock;
				}
			}
			errString = sendListing(listing);
			if (errString != null) {
				break mainblock;
			}
		}

		if (errString != null) {
			sessionThread.sendInfo(errString);
		} else {
		}
	}

	protected String makeLsString(File file) {
		StringBuilder response = new StringBuilder();

		if (!file.exists()) {
			return null;
		}

		String lastNamePart = file.getName();
		if (lastNamePart.contains("*") || lastNamePart.contains("/")) {
			return null;
		} else {
		}

		if (file.isDirectory()) {
			response.append("drwxr-xr-x 1 owner group");
		} else {
			response.append("-rw-r--r-- 1 owner group");
		}

		long fileSize = file.length();
		String sizeString = new Long(fileSize).toString();
		int padSpaces = 13 - sizeString.length();
		while (padSpaces-- > 0) {
			response.append(' ');
		}
		response.append(sizeString);

		long mTime = file.lastModified();
		SimpleDateFormat format;
		if (System.currentTimeMillis() - mTime > MS_IN_SIX_MONTHS) {
			format = new SimpleDateFormat(" MMM dd HH:mm ", Locale.US);
		} else {
			format = new SimpleDateFormat(" MMM dd  yyyy ", Locale.US);
		}
		response.append(format.format(new Date(file.lastModified())));
		response.append(lastNamePart);
		response.append("\r\n");
		return response.toString();
	}

}
